; ** por compatibilidad se omiten tildes **
; ==============================================================================
; TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
; ==============================================================================

%include "imprimir.mac"

extern GDT_DESC
extern IDT_DESC
extern idt_inicializar
extern deshabilitar_pic
extern resetear_pic
extern habilitar_pic
extern imprimir_todos_los_relojes_zombies
extern inicializar_datos_pantalla
extern imprimir_puntos_azul
extern imprimir_puntos_rojo
extern imprimir_restantes_rojo
extern imprimir_restantes_azul
extern tss_inicializar
extern pintar_posicion_zombi_jugador_azul
extern pintar_posicion_zombi_jugador_rojo
extern mmu_inicializar_dir_kernel
extern mmu_inicializar
extern game_inicializar
extern sched_inicializar

global start


;; Saltear seccion de datos
jmp start

;;
;; Seccion de datos.
;; -------------------------------------------------------------------------- ;;
iniciando_mr_msg db     'Iniciando kernel (Modo Real)...'
iniciando_mr_len equ    $ - iniciando_mr_msg

iniciando_mp_msg db     'Iniciando kernel (Modo Protegido)...'
iniciando_mp_len equ    $ - iniciando_mp_msg

nombre_grupo db "El Titanic de Homero"
nombre_grupo_len equ    $ - nombre_grupo

;;
;; Seccion de código.
;; -------------------------------------------------------------------------- ;;

%define PD_DIR 0x27000

;; Punto de entrada del kernel.
BITS 16
start:
    ; Deshabilitar interrupciones
    cli

    ; Cambiar modo de video a 80 X 50
    mov ax, 0003h
    int 10h ; set mode 03h
    xor bx, bx
    mov ax, 1112h
    int 10h ; load 8x8 font

    ; Imprimir mensaje de bienvenida
    imprimir_texto_mr iniciando_mr_msg, iniciando_mr_len, 0x07, 0, 0
    

    ; Habilitar A20
    call habilitar_A20    
    
    ; Cargar la GDT
    lgdt [GDT_DESC] 

    ; Setear el bit PE del registro CR0
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; Saltar a modo protegido
    jmp 0x40:mp	; 0x40 = 1000000b -> 1000: descriptor 8 de la GDT;
		;                 -> 000: atributos.

BITS 32
mp:
    ; Deshabilitamos las interrupciones.
    cli

    ; Configuramos el registro de segmento de datos.
    ; El 0x50 corresponde al descriptor 10 de la GDT, que es un segmento de
    ; datos de nivel (privilegio) cero. Configuramos el registro DS con el
    ; valor de ese segmento.

    mov ax, 0x50
    mov ds, ax  

    ; A los registros ES y FS les asignamos el mismo valor del registro DS.
    ; Esto tiene que ver con la posibilidad de que el código en C utilice
    ; estos registros presuponiendo que valen exactamente igual que el DS.
    
    mov es, ax
    mov fs, ax

    ; Establecer la base de la pila
    mov ss,  ax  ; AX: 0x50
    mov esp, 0x00027000
    mov ebp, esp

    ; configuramos el segmento de video
    mov ax, 0x60
    mov gs, ax

    ; Inicializar pantalla
     call inicializar_pantalla   
    
    ; Imprimir mensaje de bienvenida

    
    ; Inicializar el manejador de memoria
 
    ; Inicializar el directorio de paginas
    call mmu_inicializar

    ; inicializas la paginacion del kernel
    call mmu_inicializar_dir_kernel
  
    ; activamos paginación
    mov eax, PD_DIR
    mov cr3, eax


    ; Habilitar paginacion
    mov eax, cr0
    or  eax, 0x80000000
    mov cr0, eax	


    
    ; Inicializar tss's
    call tss_inicializar

    ; Cargamos el registro TR con el selector de la tarea inicial.
    mov ax, 0x70  ; 0x70: entrada de la tarea inicial en la gdt
    ltr ax


    ; Inicializar el scheduler

    ; Inicializar la IDT
    call idt_inicializar

    ; Cargar IDT
    lidt [IDT_DESC]
 
	
    ; Se imprime el nombre del grupo
    push nombre_grupo
    push nombre_grupo_len
    call imprimir_nombre
    lea esp, [esp + 8]

    call inicializar_datos_pantalla
    call imprimir_todos_los_relojes_zombies
    call imprimir_puntos_rojo
    call imprimir_puntos_azul
    call imprimir_restantes_rojo
    call imprimir_restantes_azul


    ; Configurar controlador de interrupciones

    ; Cargar tarea inicial

    ; se resetea el pic
    call deshabilitar_pic
    call resetear_pic
    call habilitar_pic

    call game_inicializar
    call sched_inicializar
	
    ; Habilitar interrupciones
    sti

     ; para probar 
    ; call rutina_division_0
 
   ; Saltamos a la tarea inactiva ('idle').
   jmp 0x68:0  ; 0x68: la seteamos en TSS que es la tarea idle originalmente

    ; Ciclar infinitamente (por si algo sale mal...)
    mov eax, 0xFFFF
    mov ebx, 0xFFFF
    mov ecx, 0xFFFF
    mov edx, 0xFFFF
    jmp $
    jmp $

;; -------------------------------------------------------------------------- ;;

  ; La siguiente rutina produce un error de división por cero
  ; se usó para probar el manejo de interrupciones
rutina_division_0:
  push ebp
  mov  ebp, esp
  
  xor ecx, ecx
  div ecx ; Produce el error.
 
  pop ebp
  ret

%include "imprimir_pantalla.asm"  ; Incluye la rutina para inicializar la pantalla.
%include "a20.asm"
